package cn.ch.train.generator.gen;

import cn.ch.train.generator.util.DbUtil;
import cn.ch.train.generator.util.Field;
import cn.ch.train.generator.util.FreemarkerUtil;
import freemarker.template.TemplateException;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ServerGenerator {
    static boolean readOnly = false;
    static String vuePath = "train-frontadmin/src/views/main/[module]/";
    static String basePath = "train-[module]/src/main/java/cn/ch/train/[module]/";
    static String pomPath = "generator/pom.xml";

//    static {
//        new File(basePath).mkdirs();
//    }

    public static void main(String[] args) throws DocumentException, IOException, TemplateException, SQLException {
        // 获取MyBatis-generator
        String generatorPath = getGeneratorPath();
        // 比如generator-config-member.xml，得到module=train-member
        String module = generatorPath.replace("src/main/resources/generator-config-", "")
                .replace(".xml", "");
        System.out.println("module: " + module);
        basePath = basePath.replaceAll("\\[module]", module);
        vuePath = vuePath.replaceAll("\\[module]", module);

        // 读取table节点
        Document document = new SAXReader().read("generator/" + generatorPath);
        Node table = document.selectSingleNode("//table");
        System.out.println(table);
        Node tableName = table.selectSingleNode("@tableName");
        Node domainObjectName = table.selectSingleNode("@domainObjectName");
        System.out.println(tableName.getText() + "/" + domainObjectName.getText());

        // 为DbUtil设置数据源
        Node connectionURL = document.selectSingleNode("//@connectionURL");
        Node userId = document.selectSingleNode("//@userId");
        Node password = document.selectSingleNode("//@password");
        System.out.println("连接url为: " + connectionURL);
        DbUtil.url = connectionURL.getText();
        DbUtil.user = userId.getText();
        DbUtil.password = password.getText();
        // 大写
        String Domain = domainObjectName.getText();
        // 小写
        String domain = Domain.substring(0, 1).toLowerCase() + Domain.substring(1);
        // 横线，url命名规范：全小写，多个单词用-连接
        String do_main = tableName.getText().replaceAll("_", "-");

        // 表中文名
        String tableNameCn = DbUtil.getTableComment(tableName.getText());
        List<Field> fieldList = DbUtil.getColumnByTableName(tableName.getText());
        Set<String> javaTypeSet = getJavaTypes(fieldList);


        // 组装参数
        Map<String, Object> param = new HashMap<>();
        param.put("Domain", Domain);
        param.put("domain", domain);
        param.put("do_main", do_main);
        param.put("module", module);
        param.put("tableNameCn", tableNameCn);
        param.put("fieldList", fieldList);
        param.put("javaTypeSet", javaTypeSet);
        param.put("readOnly", readOnly);
        System.out.println("组装参数: " + param);

        gen(Domain, param, "service", "service");
        gen(Domain, param, "controller/admin", "adminController");
        gen(Domain, param, "request", "saveParam");
        gen(Domain, param, "request", "queryParam");
        gen(Domain, param, "response", "queryResult");

        genVue(do_main, param, "adminVue");
    }

    private static void gen(String Domain, Map<String, Object> param, String packageName, String target) throws IOException, TemplateException {
        System.out.println("开始生成" + target);
        FreemarkerUtil.initConfig(target + ".ftl");
        String targetPath = basePath + packageName + "/";
        boolean mkdirsResult = new File(targetPath).mkdirs();
        System.out.println("创建目录" + targetPath + ": " + mkdirsResult);
        System.out.println("targetPath: " + targetPath);
        String Target = target.substring(0, 1).toUpperCase() + target.substring(1);
        String fileName = targetPath + Domain + Target + ".java";
        System.out.println("开始生成: " + fileName);
        FreemarkerUtil.generator(fileName, param);
    }

    private static void genVue(String do_main, Map<String, Object> param, String target) throws IOException, TemplateException {
        FreemarkerUtil.initConfig(target + ".ftl");
        new File(vuePath).mkdirs();
        String fileName = vuePath + "/" + do_main + ".vue";
        System.out.println("开始生成: " + fileName);
        FreemarkerUtil.generator(fileName, param);
    }

    private static String getGeneratorPath() throws DocumentException {
        SAXReader saxReader = new SAXReader();
        Map<String, String> map = new HashMap<>();
        map.put("pom", "http://maven.apache.org/POM/4.0.0");
        saxReader.getDocumentFactory().setXPathNamespaceURIs(map);
        Document document = saxReader.read(pomPath);
        // 使用XPath快速定位节点或属性
        // 先读pom中MyBatis生成器的xml配置，以明确要读的配置文件，之后再读对应的xml。要想使用XPath写法，就需要引入依赖jaxen。
        // "//"从根目录下寻找，pom是xml的命名空间，configurationFile是节点名，如果要找属性，则是@xxx。
        Node node = document.selectSingleNode("//pom:configurationFile");
        System.out.println(node.getText());
        return node.getText();
    }

    /**
     * 获取所有的Java类型，并使用Set去重（用于import对应的类）
     */
    private static Set<String> getJavaTypes(List<Field> fieldList) {
        Set<String> javaTypeSet = new HashSet<>();
        for (Field field : fieldList) {
            javaTypeSet.add(field.javaType);
        }
        return javaTypeSet;
    }
}
